﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using BFTest.Classes;
using BFTest.Ammunitions;
using BFTest.Services;
using System.Diagnostics;

namespace BFTest.Collision
{
    class CollisionManagerGC : GameComponent, ICollisionService
    {
        List<CUnit> unitList;
        List<CBullet> bulletList;
        IBattlefieldService battleFieldService;
        IBattlefieldService BattleFieldService { get { return battleFieldService; } set { battleFieldService = value; } }

        IBulletService bulletService;
        IBulletService BulletService { get { return bulletService; } set { bulletService = value; } }

        public CollisionManagerGC(Game game)
            : base(game)
        {
           
        }

        public override void Initialize()
        {
            base.Initialize();

            BattleFieldService = (IBattlefieldService)Game.Services.GetService(typeof(IBattlefieldService));
            BulletService = (IBulletService)Game.Services.GetService(typeof(IBulletService));
        }

        public void AddUnitList(List<CUnit> list)
        {
            unitList = list;
        }

        public void AddBulletList(List<CBullet> list)
        {
            bulletList = list;
        }

        public override void Update(GameTime gameTime)
        {
            
            foreach (ICollideable col in unitList)
            {
                // don't do anything yet
            }

            // bullets are going to be a special case in the collision engine, they're not going to check against other bullets, or
            // even check predicted positions of units
            List<BulletCollision> bulletCollisionList = new List<BulletCollision>();
            foreach (CBullet col in bulletList)
            {
                BulletCollision collision;
                if (CollisionDetectedAgainstUnits(col, gameTime, out collision))
                {
                    bulletCollisionList.Add(collision);
                    BulletService.DestroyBullet(collision.bulletID);
                }
            }

            foreach (BulletCollision bull in bulletCollisionList)
            {
                bull.NotifyParties(BattleFieldService);
            }
            base.Update(gameTime);
        }

        private bool CollisionDetectedAgainstUnits(CBullet col, GameTime gameTime ,out BulletCollision bCollision)
        {
            float distanceTraveledSquared = col.Velocity.LengthSquared() * (float)gameTime.ElapsedGameTime.TotalSeconds;
            foreach (ICollideable unit in unitList)
            {
                Vector2 localCoordinate = unit.Position.PointToLocalSpace(col.Position, col.Direction);
                if (Math.Abs(localCoordinate.Y) < (col.BoundingRadius * 0.5f + unit.BoundingRadius))
                {
                    float localDistanceSquared = localCoordinate.X * localCoordinate.X;
                    if (distanceTraveledSquared > localDistanceSquared)
                    {
                        // todo: fix this
                        float subFramePeriod = localDistanceSquared / distanceTraveledSquared;

                        bCollision = BulletCollision.MakeCollision(col, unit);
                        if (bCollision.ownerID != bCollision.victimID)
                            return true;
                    }
                }

            }

            bCollision = BulletCollision.MakeCollision(col, null);
            return false;
        }
    }
}
